# This program is Free Software. You can use it either under the terms of
# the GNU GPL version 3 or any later version. (c) J.Y.Amihud 2021

# This program is a very basic terminal based password manager.

from modules import hcu

# Rending an ASCI art thingy

print("""

##########################################################
#                                                        #
#                      .-..-. .-.                        #
#                      | || | | |                        #
#                      | | \ \| |                        #
#                  .-  | | _\  / _                       #
#       ____       | \_/ // \| |/ \                      # 
#      |  _ \       \___/ \_/'-'\_/                      #
#      | |_)|____                   ____                 #
#      |  __/    \.----.----.-----./    \.----.----.     #
#      | | |  /\  |  --|  --| | | |  /\  | -- |  \ |     #
#      | | |  __  |--  |--  |  .  |  \/  |  \ |  / |     #
#      '-' '-'  '-'----'----'-----'\____/'----'----'     #
#                                                        #
#                                                        #
#                                                        #
#  (C) J.Y.Amihud 2021            GNU GPL v3 or later    #
#                                                        #
##########################################################

""")



# login is just going to be an .hcu file. Which is a jason database
# This will make it easy to pull out data

import os
import json
from getpass import getpass
from modules import hcu

def login():
    
    login = input("Login: ")
    password = getpass("Password: ")
   
    # logic has to have .hcu in the end of it
    if not login.endswith(".hcu"):
        login = login+".hcu"
        
    # if the file is doesn't exist, make new file

    try:
        f = open(login, "r")
    except:
        print("File ["+login+"] doesn't exist. \nCreate? (y/n)")
        ans = input(":")

        if ans.lower() in ["y", "yes", "true"]:
            f = open(login, "w") # Making file
            f.write(hcu.hash(password)) # Giving a password hash.

            # New data
            newdata = json.dumps({})

            # Sometimes you want to restore data from a file
            try:
                restore = open("errordump_"+login.replace("/","_")+".data", "r")
                print("Restore? (y/n)")
                ans = input(":")
                if ans.lower() in ["y", "yes", "true"]:
                    newdata = restore.read()
                        
            except:
                pass
            
            f.write(hcu.code(newdata, password))
            f.close() # Exiting file
            f = open(login, "r") # reading it again

        else:
            return False
        
    # Checking that the password is correct

    if f.read(20) != hcu.hash(password):
        
        print("Wrong Password!")
        return False
    else:
        return([hcu.uncode(f.read(), password), password, login])

    
# Loging in

f = False
for i in range(10):
    if not f:
        f = login()

# If tried to login more then 10 times
if not f:
    print("Login failed.")
    input()
    exit()

# If you launched. We gonna need a few functions.

# we need to make sure that people do not loose their
# passwords
try:
    data = json.loads(f[0])
except Exception as e:
    print("WARNING! File is corrupted")
    print("Json decoding has failed: \n["+str(e)+"]")

    # Writing a special file to restore file later
    
    x = open("errordump_"+f[2].replace("/","_")+".data", "w")
    x.write(f[0])
    x.close()

    print("The un-encrypted data was saved to: errordump_"+f[2].replace("/","_")+".data")
    # Pause
    input()
    
    print(""" Restoring of data could be done! Don't worry.

1.) Open the errordump_"""+f[2].replace("/","_")+""".data file
    in the directory of the software. 

2.) Edit out all weird and strange characters. To preserve the JSON
    format, as it supposed to be. Save changes.

3.) Delete the """+f[2]+""" file. 

4.) Try to login as usual. It will ask you to create new login. Do it.
    It will ask you to restore, do it.

5.) Delete the errordump_"""+f[2].replace("/","_")+""".data file when
    restoration is successful. Test multiple times that you can enter
    your file, before deleting the un-encrypted backup.

""")

    input()
    
    print("Please report this bug to:")
    print("https://notabug.org/jyamihud/JYPassword/issues")
    exit()
    
password = f[1]
login = f[2]

print(len(data), """sites loaded. 
Type list to list all sites.
Type help to get functions.
""")

# Main loop

select = ""

while True:
    c = input(":")

    # little program to make it simpler to use. You could
    # input a number of a thing instead of the whole name

    try:
        c = int(c)

        # If you typed a number instead of the full name
        # it's going to be a shortcut, sometimes names
        # are too complex. And this is not cool.

        if not select:
            # If no site is selected
            # Then we are selecting from the list of sites

            c = list(data.keys())[c]
        else:
            c = list(data[select].keys())[c]

    # Not all commands are numbers. And not all numbers are
    # in a given dictionary. So I use a simple try: except:
    # here. Yell at me if you want.
        
    except:
        pass

    
    if c == "exit":
        exit()
    elif c == "help":
        print ("""

exit - Exits the software
help - Prints this help
list - List all sites
news - Adds a new site
newl - Add or edit a login
cpas - Change main password

""")

    # list all sites available in the file
    elif c == "list":
        for n, i in enumerate(data):
            print("[",n,"]",i)

        select = ""
            
    # add a new site to the list
    elif c == "news":
        site = input("New site name: ")
        if site not in data:
            data[site] = {}
        select = site
        print(len(data[select]), "logins in "+c)

    # User might want to change the password of the file
    elif c == "cpas":

        # we gonna check that the user knows previous password

        check = getpass("Old Password: ")
        if check == password:
            password = getpass("New Password: ")

        else:
            print("Wrong Password!")
            
    
    # if you type the name of the site then select the site    
    elif c in data:

        print(len(data[c]), "logins in "+c)
        
        for n, i in enumerate(data[c]):
            print("[",n,"]",i, " : "+"*"*len(data[c][i]))

        select = c
    
    # if any site is selected we gonna do a few more things
    elif select:

        # if you typed in a login from the site show password
        
        if c in data[select]:

           # but first we gonna check your password for this file 
            
           check = getpass("Password: ")
           if check == password:
               print("   "+data[select][c], end="\r")

               # Showing the password only for some time
               import time
               time.sleep(4)

               # Turning the password into ******** after few seconds
               ncols = len(data[select][c])
               print("   "+"*"*ncols)

           else:
               print("Wrong Password!")

                
        # if you want to add or edit a login
        
        if c == "newl":
            nlog = str(input(select+" login: "))

            # auto generate password?
            
            print("Auto-generate password? (y/n)")
            ans = input(": ")

            # Small random generator
            if ans.lower() in ["y", "yes", "true"]:
                import random
                npass = ""
                for i in range(20):
                    npass = npass + random.choice(
                        "`1234567890-=~!@#$%^&*()__+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:|ZXCVBNM<>?")

            # If you don't want to auto-generate, you can always type by hand
            else:
                npass = str(getpass(select+" password: "))

                # There is some json issues with these simbols. So let's
                # avoid them.
                npass = npass.replace('"', "'").replace("\\", "/")
                
            # adding the password to the list
            data[select][nlog] = npass

    # It will save automatically after each thing done


    f = open(login, "w") # Making file
    f.write(hcu.hash(password)) # Giving a password hash.
    f.write(hcu.code(json.dumps(data), password))
    f.close() # Exiting file
